package my.graduation.config;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Data;
import my.graduation.constant.ExamRecordStatusConstant;
import my.graduation.constant.RegRecordStatusConstant;
import my.graduation.dto.PayDto;
import my.graduation.entity.*;
import my.graduation.enums.HttpCodeEnums;
import my.graduation.result.Result;
import my.graduation.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;


import java.security.SecureRandom;
import java.sql.Date;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @Author: RavenLyn
 * @Date: 2024-12-19
 */

@ConfigurationProperties(prefix = "my-graduation.alipay")
@Component
@Data
public class AlipayConfig {
    // 应用ID,您的APPID，收款账号既是您的APPID对应支付宝账号
    @Value("{my-graduation.alipay.appId}")
    public String appId;

    // 应用私钥，就是工具生成的应用私钥
    @Value("{my-graduation.alipay.merchantPrivateKey}")
    public String merchantPrivateKey;

    // 支付宝公钥,对应APPID下的支付宝公钥。
    @Value("{my-graduation.alipay.alipayPublicKey}")
    public String alipayPublicKey;

    // 支付宝会悄悄的给我们发送一个请求，告诉我们支付成功的信息
    @Value("{my-graduation.alipay.notifyUrl}")
    public String notifyUrl;

    //同步通知，支付成功，一般跳转到成功页
    @Value("{my-graduation.alipay.returnUrl}")
    public String returnUrl;

    // 签名方式
    @Value("{my-graduation.alipay.signType}")
    private String signType;

    // 字符编码格式
    @Value("{my-graduation.alipay.charset}")
    private String charset;

    //订单超时时间
    private String timeout = "5m";
    // 支付宝网关；https://openapi-sandbox.dl.alipaydev.com/gateway.do
    @Value("{my-graduation.alipay.gatewayUrl}")
    public String gatewayUrl;

    @Autowired
    private RegistrationRecordService regRecordService;

    @Autowired
    private RegistrationScheduleService regScheService;

    @Autowired
    private RegistrationSpotsService regSpotsService;

    @Autowired
    private ExaminationRecordService examRecordService;

    @Autowired
    private ExaminationScheduleService examScheService;

    @Autowired
    private ExaminationSpotsService examSpotsService;

    @Transactional
    public Map<String,Object> pay(Record record) throws AlipayApiException {

        //1、根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new
                DefaultAlipayClient(gatewayUrl, appId, merchantPrivateKey,
                "json", charset, alipayPublicKey, signType);

        //2、创建一个支付请求，并设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(returnUrl);
        alipayRequest.setNotifyUrl(notifyUrl);

        SecureRandom random = new SecureRandom();
        int length = 10; // 假设我们需要一个10位的随机数字ID
        int id = 0; // 存储生成的ID
        for (int i = 0; i < length; i++) {
            id = id * 10 + random.nextInt(10); // 每次乘以10然后加上一个新的随机数字
        }

        long orderId =  Math.abs(id);
        String subjectTitle = (record.getRegSpotsId() != null ? "挂号预约支付" : "检查预约支付");
//        String businessType = (record.getRegSpotsId() != null ? "registration" : "examination");
        Double fee = Double.valueOf(record.getFee());

        alipayRequest.setBizContent("{"
                + "\"out_trade_no\":\"" + orderId + "\","
                + "\"total_amount\":\"" + fee + "\","
                + "\"subject\":\"" + subjectTitle + "\","
//                + "\"business_type\":\"" + businessType + "\","
                + "\"timeout_express\":\"" + timeout + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        String payPage = alipayClient.pageExecute(alipayRequest).getBody();
        //会收到支付宝的响应，响应的是一个页面，只要浏览器显示这个页面，就会自动来到支付宝的收银台页面
        System.out.println("支付宝的响应：" + payPage);

        Map<String,Object> response = new HashMap<>();
        response.put("orderId", orderId);
        response.put("payPage", payPage);

        if(record.getRegSpotsId() != null){
            // 创建挂号记录 + 占号
            regSpotsService.gainOne(record.getRegSpotsId()); //占号

            RegistrationRecord newOne = new RegistrationRecord();
            BeanUtils.copyProperties(record,newOne);
            newOne.setId(null);
            newOne.setOrderId((int) orderId);
            newOne.setStatus(RegRecordStatusConstant.UNPAID); //0 是待支付
            regRecordService.save(newOne);
        }else {
            // 更新检查预约记录 + 占号
            examSpotsService.gainOne(record.getExamSpotsId()); //占号

            ExaminationRecord newOne = new ExaminationRecord();
            BeanUtils.copyProperties(record,newOne);
            newOne.setId(record.getExamRecordId());
            newOne.setOrderId((int) orderId);
            newOne.setCheckDoctorId(record.getDoctorId());
            newOne.setStatus(ExamRecordStatusConstant.UNPAID); //0 是待支付
            System.out.println(record.getExamRecordId());
            boolean b = examRecordService.updateById(newOne);
            System.out.println(b);

        }


        return response;
    }

    /**
     * 退款 还号
     * @param record
     * @return
     */
    public String refund(Record record) throws AlipayApiException{
        //1、根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new
                DefaultAlipayClient(gatewayUrl, appId, merchantPrivateKey,
                "json", charset, alipayPublicKey, signType);

        //2、创建一个退款请求，并设置请求参数
        AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", record.getOrderId());
        DecimalFormat df = new DecimalFormat("#.00");
        bizContent.put("refund_amount",df.format(record.getFee()) );
//        bizContent.put("out_trade_no", "1252151918");
//        bizContent.put("refund_amount","20.00" );

        refundRequest.setBizContent(bizContent.toString());
//        System.out.println(record.getRegRecordId());

//        AlipayTradeQueryRequest queryRequest = new AlipayTradeQueryRequest();
//        JSONObject queryBizContent = new JSONObject();
//        queryBizContent.put("out_trade_no", record.getOrderId());
//        queryRequest.setBizContent(queryBizContent.toString());
//
//        AlipayTradeQueryResponse queryResponse = alipayClient.execute(queryRequest);
//        if (queryResponse.isSuccess()) {
//            System.out.println("订单状态: " + queryResponse.getTradeStatus());
//        }

        try{
            AlipayTradeRefundResponse response = alipayClient.execute(refundRequest);
            if(response.isSuccess()){
                // 还号 remainSpots + 1  status = 3
                if(record.getRegRecordId() != null){
                    Integer regSpotsId = record.getRegSpotsId();
                    if(regSpotsId == null){
                        RegistrationRecord recordOne = regRecordService.getOne(Wrappers.<RegistrationRecord>lambdaQuery()
                                .eq(RegistrationRecord::getId, record.getRegRecordId()));
                        Integer doctorId = recordOne.getDoctorId();
                        Date date = recordOne.getDate();
                        Integer timeSlot = recordOne.getTimeSlot();
                        Integer shift;
                        if(timeSlot < 6){ // 0-5 shift:0
                            shift = 0;
                        }else{ // 6-11 shift:1
                            shift = 1;
                        }
                        RegistrationSchedule scheOne = regScheService.getOne(Wrappers.<RegistrationSchedule>lambdaQuery()
                                .eq(RegistrationSchedule::getDoctorId, doctorId)
                                .eq(RegistrationSchedule::getDate, date)
                                .eq(RegistrationSchedule::getShift, shift));
                        RegistrationSpots spotsOne = regSpotsService.getOne(Wrappers.<RegistrationSpots>lambdaQuery()
                                .eq(RegistrationSpots::getRegScheId, scheOne.getId())
                                .eq(RegistrationSpots::getTimeSlot, timeSlot));
                        regSpotsId = spotsOne.getId();
                    }
                    regSpotsService.returnOne(regSpotsId); //还号
                    regRecordService.updateStatus(record.getOrderId(), RegRecordStatusConstant.CANCELED); // 取消
                } else {
                    Integer examSpotsId = record.getExamSpotsId();
                    ExaminationRecord recordOne = examRecordService.getOne(Wrappers.<ExaminationRecord>lambdaQuery()
                            .eq(ExaminationRecord::getId, record.getExamRecordId()));
                    if(examSpotsId == null){
                        Integer doctorId = recordOne.getCheckDoctorId();
                        Date date = recordOne.getDate();
                        Integer timeSlot = recordOne.getTimeSlot();
                        Integer shift;
                        if(timeSlot < 6){ // 0-5 shift:0
                            shift = 0;
                        }else{ // 6-11 shift:1
                            shift = 1;
                        }
                        ExaminationSchedule scheOne = examScheService.getOne(Wrappers.<ExaminationSchedule>lambdaQuery()
                                .eq(ExaminationSchedule::getDoctorId, doctorId)
                                .eq(ExaminationSchedule::getDate, date)
                                .eq(ExaminationSchedule::getShift, shift));
                        ExaminationSpots spotsOne = examSpotsService.getOne(Wrappers.<ExaminationSpots>lambdaQuery()
                                .eq(ExaminationSpots::getExamScheId, scheOne.getId())
                                .eq(ExaminationSpots::getTimeSlot, timeSlot));
                        examSpotsId = spotsOne.getId();
                    }
                    examSpotsService.returnOne(examSpotsId); //还号
                    examRecordService.updateStatus(record.getOrderId(), ExamRecordStatusConstant.CANCELED); // 取消
                    ExaminationRecord newOne = new ExaminationRecord();
                    BeanUtils.copyProperties(recordOne,newOne);
                    newOne.setId(null);
                    newOne.setOrderId(null);
                    newOne.setStatus(ExamRecordStatusConstant.UNPAID);
                    newOne.setCheckDoctorId(null);
                    newOne.setDate(null);
                    newOne.setTimeSlot(null);
                    newOne.setPayTime(null);
                    boolean i = examRecordService.save(newOne);
                    System.out.println(i);
                }
                System.out.println("退款成功");
                return "success";
            } else {
                System.out.println("错误码: " + response.getSubCode());
                System.out.println("错误信息: " + response.getSubMsg());
                System.out.println("退款失败");
                return "failure";
            }
        }catch (Exception e) {
            e.printStackTrace();
            return "failure";
        }
    }
}
